﻿using Android.App;
using Android.OS;
using Android.Runtime;
using Android.Widget;
using Android;
using Android.Views;
//using Com.Espressif.Iot.Esptouch;
using Android.Content.PM;
using Android.Locations;
using Android.Net.Wifi;
using Android.Content;
using System;
using System.Linq;
using Com.Espressif.Iot.Esptouch;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Threading;
using AndroidX.AppCompat.App;
using Google.Android.Material.Button;
using Google.Android.Material.TextField;
using AlertDialog = AndroidX.AppCompat.App.AlertDialog;

namespace AppEspTouch
{
    [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)]
    public class MainActivity : AppCompatActivity
    {
        const int MENU_ITEM_ABOUT = 0;

        TextView _message;
        MaterialButton _btnConfirm;
        TextView _ssid;
        TextView _bssid;
        TextInputEditText _password;
        RadioGroup _packageModeGroup;
        EsptouchTask _esptouch;

        bool _isRegisterReceiver = false;
        WifiBroadcastReceiver _receiver;

        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            Xamarin.Essentials.Platform.Init(this, savedInstanceState);
            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.activity_main);

            _ssid = FindViewById<TextView>(Resource.Id.ap_ssid_text);
            _bssid = FindViewById<TextView>(Resource.Id.ap_bssid_text);
            _password = FindViewById<TextInputEditText>(Resource.Id.ap_password_edit);
            _packageModeGroup = FindViewById<RadioGroup>(Resource.Id.package_mode_group);
            _message = FindViewById<TextView>(Resource.Id.message);
            _btnConfirm = FindViewById<MaterialButton>(Resource.Id.confirm_btn);
            var deviceCountEdit = FindViewById<TextInputEditText>(Resource.Id.device_count_edit);
            deviceCountEdit.Text = "1";

            _receiver = new WifiBroadcastReceiver();
            _receiver.OnWifiChanged += (info) =>
            {
                OnWifiChanged(info);
            };

            _btnConfirm.Click += async (s, e) =>
            {
                var count = deviceCountEdit.Text.Trim().Length == 0 ? -1 : int.Parse(deviceCountEdit.Text);
                _esptouch = new EsptouchTask(_ssid.Text, _bssid.Text, _password.Text, this);
                _esptouch.SetPackageBroadcast(_packageModeGroup.CheckedRadioButtonId == Resource.Id.package_broadcast);

                var ct = new CancellationTokenSource();

                // 显示智能组网进度条
                var progressDialog = new ProgressDialog(this);
                progressDialog.SetMessage(GetString(Resource.String.configuring_message));
                progressDialog.SetCanceledOnTouchOutside(false);
                progressDialog.CancelEvent += async (s, e) =>
                {
                    if (_esptouch != null)
                    {
                        await Task.Run(() =>
                        {
                            ct.Cancel();
                            _esptouch.Interrupt();
                        });
                    }
                };
                progressDialog.SetButton((int)DialogButtonType.Negative, GetText(Android.Resource.String.Cancel), async (s, e) =>
                {
                    if (_esptouch != null)
                    {
                        await Task.Run(() =>
                        {
                            ct.Cancel();
                            _esptouch.Interrupt();
                        });
                    }
                });
                progressDialog.Show();

                await Task.Run(() =>
                {
                    var results = _esptouch.ExecuteForResults(count);

                    if (!ct.IsCancellationRequested)
                    {
                        // 组网完毕显示成功
                        progressDialog.Dismiss();
                        if (results != null)
                        {
                            RunOnUiThread(() =>
                            {
                                var resultDialog = new AlertDialog.Builder(this)
                                   .SetMessage(Resource.String.configure_result_failed_port)
                                   .SetPositiveButton(Android.Resource.String.Ok, (s, e) => { })
                                   .Show();
                                resultDialog.SetCanceledOnTouchOutside(false);
                            });
                        }
                    }
                }, ct.Token);
            };

            if (Build.VERSION.SdkInt >= BuildVersionCodes.OMr1)
            {
                var prmissions = new[] { Manifest.Permission.AccessCoarseLocation, Manifest.Permission.AccessFineLocation };
                var count = prmissions.Where(p => CheckSelfPermission(p) == Permission.Denied).Count();

                if (count > 0)
                {
                    RequestPermissions(prmissions, 0);
                }
                else
                {
                    RegisterBroadcastReceiver();
                }
            }
            else
            {
                RegisterBroadcastReceiver();
            }
        }

        private void RegisterBroadcastReceiver()
        {
            var filter = new IntentFilter(WifiManager.NetworkStateChangedAction);
            if (Build.VERSION.SdkInt >= BuildVersionCodes.P)
            {
                filter.AddAction(LocationManager.ProvidersChangedAction);
            }
            RegisterReceiver(_receiver, filter);
            _isRegisterReceiver = true;
        }

        protected override void OnDestroy()
        {
            base.OnDestroy();

            if (_isRegisterReceiver)
            {
                UnregisterReceiver(_receiver);
            }
        }

        public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
        {
            if (requestCode == 0)
            {
                RegisterBroadcastReceiver();
            }

            Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);

            base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
        }

        public override bool OnCreateOptionsMenu(IMenu menu)
        {
            menu.Add(Menu.None, MENU_ITEM_ABOUT, 0, Resource.String.menu_item_about)
                .SetIcon(Resource.Drawable.ic_info_outline_white_24dp)
                .SetShowAsAction(ShowAsAction.Always);
            return base.OnCreateOptionsMenu(menu);
        }

        public override bool OnOptionsItemSelected(IMenuItem item)
        {
            if (item.ItemId == MENU_ITEM_ABOUT)
            {
                ShowAboutDialog();
                return true;
            }

            return base.OnOptionsItemSelected(item);
        }

        private void ShowAboutDialog()
        {
            var esptouchVer = EsptouchTask.EsptouchVersion;
            var appVer = "";
            try
            {
                var info = PackageManager.GetPackageInfo(PackageName, 0);
                appVer = info.VersionName;
            }
            catch (PackageManager.NameNotFoundException e)
            {
                e.PrintStackTrace();
            }

            var items = new[]{
                GetString(Resource.String.about_app_version, appVer),
                GetString(Resource.String.about_esptouch_version, esptouchVer),
            };

            new AlertDialog.Builder(this)
                    .SetTitle(Resource.String.menu_item_about)
                    .SetIcon(Resource.Drawable.ic_info_outline_black_24dp)
                    .SetItems(items, (s, e) => { })
                    .Show();
        }

        // 检查定位
        private void CheckLocation()
        {
            var locationManager = (LocationManager)GetSystemService(Context.LocationService);
            var enable = locationManager?.IsLocationEnabled ?? false;
            if (!enable)
            {
                _message.SetText(Resource.String.location_disable_message);
            }
        }

        // 获得当前wifi信息
        private void OnWifiChanged(WifiInfo info)
        {
            var disconnected = (info == null || info.NetworkId == -1 || info.SSID == "<unknown ssid>");
            if (disconnected)
            {
                _message.SetText(Resource.String.no_wifi_connection);
                _btnConfirm.Enabled = false;
            }
            else
            {
                var ssid = info.SSID;
                if (ssid.StartsWith("\"") && ssid.EndsWith("\""))
                {
                    ssid = ssid[1..^1];
                }
                _ssid.Text = ssid;
                //_ssid.Tag = ByteUtil.GetBytesByString(ssid);
                //var ssidOriginalData = TouchNetUtil.GetOriginalSsidBytes(info);
                //_ssid.Tag = ssidOriginalData;

                var bssid = info.BSSID;
                _bssid.Text = bssid;

                _btnConfirm.Enabled = true;
                _message.Text = "";
                if (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop)
                {
                    int frequency = info.Frequency;
                    if (frequency > 4900 && frequency < 5900)
                    {
                        // Connected 5G wifi. Device does not support 5G
                        _message.SetText(Resource.String.wifi_5g_message);
                    }
                }
            }
        }

        class WifiBroadcastReceiver : BroadcastReceiver
        {
            public Action<WifiInfo> OnWifiChanged;

            public override void OnReceive(Context context, Intent intent)
            {
                var action = intent.Action;
                if (action == null)
                {
                    return;
                }

                WifiManager wifiManager = (WifiManager)context.ApplicationContext.GetSystemService(Context.WifiService);

                switch (action)
                {
                    case WifiManager.NetworkStateChangedAction:
                    case LocationManager.ProvidersChangedAction:
                        OnWifiChanged?.Invoke(wifiManager.ConnectionInfo);
                        break;
                }
            }
        }
    }
}